Core.Storage.Dao = {
		
	/**
	 * Creates the Data Access Object from the given path & local storage.
	 * @param String|Array raw
	 * @param Any storage*
	 */
	create: function(raw, storage) {
		if(!storage) { storage = Core.Storage.Raw; }

		var arr = (typeof raw === "string") ? 
				Core.Storage.Dao.compile(raw) 
			:	raw;
		
		return Core.Storage.Dao.isPlain(arr) ?
				new Core.Storage.Dao.Simple(arr, storage) 
			:	new Core.Storage.Dao.Complex(arr, storage);
	},
	
	/**
	 * Returns true if the given array path does not contain any Array elements.
	 * @param Array arr
	 */
	isPlain: function(arr) {
		for(var i = 1, l = arr.length; i < l; i++) {
			if(typeof arr[i] !== "string") {
				return false;
			}
		}
		return true;
	},
	
	/**
	 * Transforms the given string raw path into array-based compiled path.
	 * @param String raw
	 */
	compile: function(raw) {
		var arr = [], stack = [], pt = 0,
			raw = raw.replace(/ /g, ""), l = raw.length,
			
			indexOf = function(token) {
				var idx = raw.indexOf(token, pt);
				return idx < 0 ? Number.MAX_VALUE : idx;
			},
			
			didx = indexOf("."),
			csidx = indexOf("{"),
			ceidx = indexOf("}");
		
		while(pt < l) {
			// . { } all not found
			if(didx === Number.MAX_VALUE && csidx === Number.MAX_VALUE && ceidx === Number.MAX_VALUE) {
				arr.push(raw.substr(pt));
				break;
			}
			// . handling
			if(didx < csidx && didx < ceidx) {
				if(arr.length === 0) {
					arr[0] = raw[didx + 1] === ".";
					pt = didx + (arr[0] ? 2 : 1);
				} else {
					arr.push(raw.substring(pt, didx));
					pt = didx+1;
				}
				didx = indexOf(".");
			}
			// { handling
			if(csidx < didx && csidx < ceidx) {
				if(pt !== csidx) { arr.push(raw.substring(pt, csidx)); }
				pt = csidx+1;
				
				stack.push(arr);
				arr.push([]);
				arr = arr.last();
				
				csidx = indexOf("{");
			}
			// } handling
			if(ceidx < didx && ceidx < csidx) {
				if(pt !== ceidx) { arr.push(raw.substring(pt, ceidx)); }
				pt = ceidx+1;
				
				arr = stack.pop();
				ceidx = indexOf("}");
			}
		}
		return arr;
	}
};